package ch.trackedbean.client.gui;

import java.awt.*;
import java.awt.event.*;
import java.util.List;
import javax.swing.*;
import ch.trackedbean.binding.action.*;

/**
 * {@link AbstractAsynchronousAction} showing an wait cursor and the text specified by {@link #getProgressBarText()} in the progressbar.
 * 
 * @param <S> The type of the selection
 * @param <P> The type of the prepared object (created by {@link #prepare(ActionEvent, List)})
 * @param <R> The type of the result object (created by {@link #perform(ActionEvent, Object, List)})
 * @author hautle
 */
public abstract class ServerAction<S, P, R> extends AbstractAsynchronousAction<S, P, R> {
    /**
     * Default constructor.
     */
    public ServerAction() {
    }

    /**
     * Default constructor.
     * 
     * @param name The name of the action
     * @param icon The icon of the action
     */
    public ServerAction(String name, Icon icon) {
        super(name, icon);
    }

    /**
     * Default constructor.
     * 
     * @param name The name of the action
     */
    public ServerAction(String name) {
        super(name);
    }

    /**
     * Returns the text which should be displayed in the progressbar.
     * 
     * @return The text to display in the progressbar.
     */
    protected abstract String getProgressBarText();

    /**
     * {@inheritDoc}
     */
    @Override
    protected final P prepare(ActionEvent e, List<S> selection) throws Exception {
        MainFrame.ME.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        MainFrame.ME.showProgressBar(getProgressBarText());
        return prepareHook(e, selection);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected final void finish(ActionEvent e, P prepare, R result, List<S> selection) {
        finishHook(e, prepare, result, selection);
        MainFrame.ME.setCursor(Cursor.getDefaultCursor());
        MainFrame.ME.hiddeProgressBar();
    }

    /**
     * Hook method called after the execution of {@link #perform(ActionEvent, Object, List)} (also if the call failed).<br>
     * Use this method for releasing locks etc.<br>
     * This method gets executed on the Event Dispatch Thread.
     * 
     * @param e The action event
     * @param prepare The result returned by {@link #prepare(ActionEvent, List)}
     * @param result The result returned by {@link #perform(ActionEvent, Object, List)} or null if the call failed
     * @param selection The selection
     */
    protected void finishHook(ActionEvent e, P prepare, R result, List<S> selection) {
    }

    /**
     * Hook method called before the asynchronous part starts.<br>
     * 
     * @param e The action event
     * @param selection The selection
     * @return The result of the preparation (will be passed to {@link #perform(ActionEvent,Object, List)})
     * @throws Exception If something went wrong (will be handled by the handler returned by {@link #getExceptionHandler()})
     */
    protected P prepareHook(ActionEvent e, List<S> selection) throws Exception {
        return null;
    }
}
